#pragma once

#include <iostream>
#include <string>
#include <string.h>
#include <sys/socket.h>
#include <sys/types.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include "log.hpp"

static const int g_bak = 10;

class Sock
{
public:
    Sock(){}
    ~Sock(){}

public:
    void Socket()
    {
        m_sock = socket(AF_INET, SOCK_STREAM , 0);
        if(m_sock < 0)
        {
            // TODO
        }
        int opt = 1;
        setsockopt(m_sock, SOL_SOCKET, SO_REUSEADDR|SO_REUSEPORT, &opt, sizeof(opt));
    }

    void Bind(uint16_t port)
    {
        struct sockaddr_in server;
        memset(&server, 0, sizeof(server));
        server.sin_family = AF_INET;
        server.sin_port = htons(port);
        server.sin_addr.s_addr = INADDR_ANY;

        if(bind(m_sock, (struct sockaddr*)&server, sizeof(server)) < 0)
        {
            // todo
        }
    }

    void Listen()
    {
        if(listen(m_sock, g_bak) < 0)
        {
            // todo
        }
    }

    int Accept(std::string* ip, uint16_t* port)
    {
        struct sockaddr_in client;
        socklen_t len = sizeof(client);
        int newfd = accept(m_sock, (struct sockaddr*)&client, &len);
        if(newfd < 0)
        {
            // todo
        }
        *port = ntohs(client.sin_port);
        char ipstr[64];
        inet_ntop(AF_INET, &client.sin_addr, ipstr, sizeof(ipstr));
        *ip = ipstr;

        return newfd;
    }
private:
    int m_sock;
};